package com.car.framework;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.graphics.Bitmap;
import com.car.comm.Assert;
import com.car.comm.ErrorAgent;
import com.car.comm.Logger;
import com.car.comm.Outter;
import com.car.comm.Variable;
import com.car.image.SerializeBitmap;
import com.car.postoffice.CAddress;
import com.car.postoffice.CMail;
import com.car.postoffice.CMailHeader;
import com.car.postoffice.CMailReply;
import com.car.postoffice.SendException;
import com.car.postoffice.TPostMark;
import com.car.postoffice.UnSupportedScheme;

/**
 *  图像管理器，负责控制所有的图像实例，句柄等
 * @author Xairy
 *
 */
class ImageManager extends FrameActivity {
	private static final int EInValid = 0;
	private static final int EInRequesting = 1;
	private static final int ESuccess = 2;
	private static final int EFailed = 3;
	private static int lastId = 1;
	private class Image{
		public SerializeBitmap instance;
		public String uri;
		public int id;
		public List<CAddress> observerList;
		public int state;
		public TPostMark mark;
		
		public Image(String uri){
			this.instance = new SerializeBitmap();
			this.uri = uri;
			this.id = ImageManager.lastId++;
			this.state = EInValid;
			this.observerList = new ArrayList<CAddress>();
		}
	}
	
	private HashMap<String, Image> uriMap = new HashMap<String, Image>();
	private HashMap<Integer, Image> idMap = new HashMap<Integer, Image>();
	
	public ImageManager(){
		super.SetUpBackGround("image");
	}
	
	/**
	 * 获取一个图片，同时返回该图片的id
	 * @param   addr[in] 句柄持有者
	 * @param   uri[in]  图片的地址
	 * @param   instance[out] 如果存在改实例，则填充实例，否则填充空
	 * @return  图片的id
	 * @throws UnSupportedScheme 
	 * @throws SendException 
	 */
	public int GetImage(CAddress addr, 
						String uri,
						Outter<Bitmap> bitmap) throws SendException{
		Image img = uriMap.get(uri);
		if(img == null){
			// 说明图片是第一次请求
			img = new Image(uri);
		}
		if(!img.observerList.contains(addr)){
			img.observerList.add(addr);
		}
		if(img.state == EInRequesting){
			return img.id;
		}else if(img.state == ESuccess){
			bitmap.setInstance(img.instance.getBmpInstance());
			return img.id;
		}
		
		// 失败的或者未请求过的图像，触发请求
		String scheme = null;
		String path = null;
		if(uri.startsWith("local://")){
			scheme = Variable.httpLocal;
			path = uri.substring(8);
		}else if(uri.startsWith("http://")){
			scheme = Variable.httpGetScheme;
			path = uri.substring(7);
		}else{
			throw new IllegalArgumentException("uri format error");
		}
		
		CMail mail = new CMail(this.addr, new CAddress(scheme, path));
		mail.getHeader().setMailType(Variable.bitmapType);
		mail.getHeader().setMailId(img.id);
		
		try{
			 img.mark = office.SendMail(mail, Variable.levelLow,
								FrameworkFactory.GetBitmapMapping());
		}catch(UnSupportedScheme e){
			Assert.TRUE(false, e.getMessage());
		}
		img.state = EInRequesting;
		if(!uriMap.containsKey(img.uri)){
			uriMap.put(img.uri, img);
		}
		if(!idMap.containsKey(img.id)){
			idMap.put(img.id, img);
		}
		return img.id;
	}
	
	/**
	 * 主动释放对一个图片的持有
	 * @param id
	 * @return
	 */
	public void ReleaseImage(CAddress addr, int id){
		Image img = idMap.get(id);
		if(img == null){
			return ;
		}
		img.observerList.remove(addr);
		if(img.observerList.size() == 0){
			if(img.state == EInRequesting){
				office.CancelMail(img.mark);
			}
			uriMap.remove(img.uri);
			idMap.remove(id);
		}
	}
	
	public Bitmap Instance(int id){
		Image img = idMap.get(id);
		if(img == null){
			return null;
		}
		return img.instance.getBmpInstance();
	}
	
	@Override
	public void HandleReply(CMailReply reply) {
		CMailHeader header = reply.getHeader();
		if(!header.getMailType().equals(Variable.bitmapType)){
			Logger.LogErr("Reply" + header +" not image send to ImageManager");
			return ;
		}
		Image img = this.idMap.get(header.getMailId());
		if(img == null){
			Logger.LogRun("Cannot found " + header.getMailId() + " image");
			return ;
		}
		
		CMailReply notifyReply = new CMailReply();
		notifyReply.setHeader(reply.getHeader());
		notifyReply.setResult(reply.getResult());
		
		Object mailObj = reply.getMailObj();
		if(mailObj != null && mailObj instanceof SerializeBitmap){
			img.instance = (SerializeBitmap) mailObj;
			img.state = ESuccess;
			notifyReply.getResult().setErrorCode(0);
		}else{
			img.state = EFailed;
			notifyReply.getResult().setErrorCode(ErrorAgent.EDownloadFailed);
		}
		
		NotifyAll(img, notifyReply);
	}
	
	private void NotifyAll(Image img, CMailReply reply){
		for(CAddress dstAddr : img.observerList){
			office.NotifyMail(dstAddr, reply);
		}
	}
}
